﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Net;
using System.Net.Sockets;
using System.Security.Principal;
using System.IO;

namespace SPRemoteService.WinApp
{
    public partial class RemoteServiceConfigForm : Form
    {
        ServiceHost _host;
        MainForm _mainForm;

        public RemoteServiceConfigForm(ServiceHost host, MainForm mainForm)
        {
            InitializeComponent();
            _host = host;
            _mainForm = mainForm;
        }

        private void RemoteServiceConfigForm_Load(object sender, EventArgs e)
        {
            this.CenterToParent();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            txtApplicationID.Enabled = chkEnableRemoteService.Checked;

            if (chkEnableRemoteService.Checked)
            {
                try
                {
                    txtApplicationID.Text = EnableRemoteServiceTcp();
                    if (txtApplicationID.Text == "") chkEnableRemoteService.Checked = false;
                }
                catch (Exception ex)
                {
                    chkEnableRemoteService.Checked = false;
                    MessageBox.Show(ex.Message);
                    DisableRemoteService();
                }
            }
            else
            {
                DisableRemoteService();
            }
        }

        private void DisableRemoteService()
        {
            //_host.Close();
            _mainForm.listenerThread.Abort();
            txtApplicationID.Text = "";
        }

        private string EnableRemoteServiceTcp()
        {
            string temp = EnableRemoteService();

            string appId = "";
            try
            {
                //Connect to server
                _mainForm.tcpClient = new TcpClient();
                _mainForm.tcpClient.Connect(_mainForm.Connector.SiteUrl.Host, 10080);

                //Get reader stream
                StreamReader reader = new StreamReader(_mainForm.tcpClient.GetStream());
                string line = reader.ReadLine();
                appId = line;
                _mainForm.listenerThread.IsBackground = true;
                _mainForm.listenerThread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return appId;
        }


        private string EnableRemoteService()
        {
            string result = "";
            IPHostEntry host;
            string localIP = "?";
            host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    localIP = ip.ToString();

                    Uri baseAddress = new Uri(String.Format("http://{0}:8080/WinAppRemoteService", localIP));

                    // Create the ServiceHost.
                    _host = new ServiceHost(typeof(WinAppRemoteService), baseAddress);

                    // Enable metadata publishing.
                    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                    smb.HttpGetEnabled = true;
                    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                    _host.Description.Behaviors.Add(smb);

                    // For .NET 3.5
                    //_host.AddServiceEndpoint(typeof(IWinAppRemoteService), new BasicHttpBinding(), baseAddress);
                    //_host.AddServiceEndpoint(typeof(IWinAppRemoteService), new BasicHttpBinding(), baseAddress + "SayHello");

                    // Open the ServiceHost to start listening for messages. Since
                    // no endpoints are explicitly configured, the runtime will create
                    // one endpoint per base address for each service contract implemented
                    // by the service.
                    _host.Open();


                    //Register
                    BasicHttpBinding binding = new BasicHttpBinding();
                    binding.Name = "basicBindingEndPoint";
                    binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
                    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;

                    binding.MaxBufferPoolSize = Int32.MaxValue;
                    binding.MaxReceivedMessageSize = Int32.MaxValue;
                    binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
                    binding.ReaderQuotas.MaxBytesPerRead = Int32.MaxValue;

                    string endpointUrl = _mainForm.Connector.SiteUrl.ToString();
                    if (endpointUrl.EndsWith("/"))
                    {
                        endpointUrl = endpointUrl.Substring(0, endpointUrl.Length - 1);
                    }
                    
                    endpointUrl = endpointUrl + @"/_vti_bin/RemoteService/RemoteService.svc";
                    SPRemoteServiceRef.RemoteServiceClient port = new SPRemoteServiceRef.RemoteServiceClient(binding, new EndpointAddress(endpointUrl));

                    port.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
                    port.ClientCredentials.Windows.ClientCredential = new NetworkCredential(_mainForm.Connector.UserName, _mainForm.Connector.Password, _mainForm.Connector.Domain);

                    result = port.RegisterApp(baseAddress.ToString());

                    if (!String.IsNullOrEmpty(result))
                    {
                        break;
                    }
                    else
                    {
                        _host.Close();
                    }
                }
            }

            return result;

        }

        private void RemoteServiceConfigForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.Hide();
        }

        private void StartHost()
        {
            _host.Open();
        }
    }
}
